package com.frxuexi.lib_base.mvi

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import androidx.paging.cachedIn
import com.frxuexi.lib_base.entity.ParkBeanItem
import com.frxuexi.lib_base.entity.Res
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import java.text.SimpleDateFormat
import java.util.Random

abstract class BaseViewModel<UiIntent : IUiIntent> : ViewModel() {
    val channel = Channel<UiIntent>()

    private var _state = MutableStateFlow<UiState>(UiState.onLoading)
    val uiState: StateFlow<UiState>
        get() = _state.asStateFlow()

    init {
        viewModelScope.launch {
            //接收意图
            channel.receiveAsFlow().collect {
                handlerIntent(it)
            }
        }


    }

    //处理意图
    abstract fun handlerIntent(it: UiIntent)

    /**
     * 发送意图
     * intent：意图
     */
    fun sendIntent(intent: UiIntent) {
        viewModelScope.launch {
            channel.send(intent)
        }
    }

    /**
     * 网络请求
     */
    fun <T> httpRequest(request: Flow<Res<T>>, type: RequestType = RequestType.DEFAULT) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.i("lr", it.message.toString())
                }.collect {
                    if (it.code == 200) {
                        if (type == RequestType.DELETE) {
                            val num = Random().nextInt()
                            _state.value = UiState.onSuccess("${it.data},${num}", type)
                        } else {
                            _state.value = UiState.onSuccess(it.data, type)
                        }
                    } else {
                        _state.value = UiState.onError(it.message)
                    }
                }
        }
    }

    /**
     * room请求
     */
    fun <T> roomRequest(request: Flow<T>, type: RequestType = RequestType.DEFAULT) {
        viewModelScope.launch {
            request.flowOn(Dispatchers.IO)
                .catch {
                    Log.i("lr", it.message.toString())
                }.collect {
                    if (it != null) {
                        _state.value = UiState.onSuccess(it, type)
                    } else {
                        _state.value = UiState.onError("操作失败")
                    }
                }
        }
    }

    fun <T : Any> pagingRequest(
        pagingSource: () -> PagingSource<Int, T>
    ) {
        val dataFlow = Pager(PagingConfig(pageSize = 10),
            pagingSourceFactory = {
                pagingSource()
            }
        ).flow.cachedIn(viewModelScope)

        viewModelScope.launch {
            dataFlow.flowOn(Dispatchers.IO)
                .catch {
                    _state.value = UiState.onError(it.message ?: "未知错误")
                }.collect {
                    _state.value = UiState.onSuccess(it)
                }
        }
    }

    fun toBody(bean: Any): RequestBody {
        val json = Gson().toJson(bean)
        return RequestBody.create("application/json".toMediaTypeOrNull(), json)
    }

    fun getDataTimeString(time: Long): String {
        return SimpleDateFormat("yyyyMMddHHmmss").format(time)
    }

    fun getDataTime(time: Long): String {
        return SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time)
    }

    fun getTime(time: Long): String {
        return SimpleDateFormat("HH:mm:ss").format(time)
    }

    fun getData(time: Long): String {
        return SimpleDateFormat("yyyy-MM-dd").format(time)
    }

    fun getDataFont(time: Long): String {
        return SimpleDateFormat("yyyy年MM月dd日").format(time)
    }

}